package com.sopt.eat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.database.sqlite.SQLiteDatabase;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;

import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;

import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.sopt.eat.db.EatDBHelper;
import com.sopt.eat.db.Constants.EatDB;
import com.sopt.eat.statics.EatVars;
import com.sopt.eat.views.CenterPointOverlay;
import com.sopt.eat.views.ChoicedItemizedOverlay;
import com.sopt.eat.views.ResultPointItemizedOverlay;
import com.sopt.eat.vo.SearchItem;

public class EatMapActivity extends MapActivity implements View.OnClickListener {
	private MapView mapView;

	private Location currentLocation;
	private Double currentLat;
	private Double currentLot;
	private LocationListener onLocationUpdate;
	private LocationManager locationManager;

	private TextView categoryText;
	private Button getListButton;
	private Button getCurrentLocationButton;

	private ProgressDialog progressDialog;
	private ArrayList<JSONObject> result;
	private ArrayList<SearchItem> searchedList;

	private Geocoder geocoder;
	private ResultPointItemizedOverlay itemizedOverlay;

	private RelativeLayout bottomDetailViewLayer;

	private SearchItem currentSearchItem;

	private ChoicedItemizedOverlay choicedItemizedOverlay;

	private int firstFlag;

	private List<Overlay> mapOverlays;

	protected void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		firstFlag=0;
		setContentView(R.layout.mapview);

		init();

	}

	private void init() {

		mapView = (MapView) findViewById(R.id.mapviews);
		categoryText = (TextView) findViewById(R.id.categoryText);
		bottomDetailViewLayer = (RelativeLayout) findViewById(R.id.bottomMapViewLayout);

		categoryText.setText("CurrentCategory : "
				+ getIntent().getExtras().getString("currentCategory"));
		getListButton = (Button) findViewById(R.id.getListButton);
		getCurrentLocationButton  = (Button) findViewById(R.id.buttonGetCurrentLocation);
		
		getListButton.setOnClickListener(this);
		getCurrentLocationButton.setOnClickListener(this);
		
		mapView.setBuiltInZoomControls(true);

		mapView.getController().setZoom(mapView.getMaxZoomLevel() - 2);

		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		
		geocoder = new Geocoder(this);
		currentLocation = new Location(LocationManager.GPS_PROVIDER);
		currentLat = mapView.getMapCenter().getLatitudeE6() / 1E6;
		currentLot = mapView.getMapCenter().getLongitudeE6() / 1E6;
		currentLocation.setLatitude(currentLat);
		currentLocation.setLongitude(currentLot);
		
		
		setLocation(currentLocation,false);
	}

	protected void setItemsToMapView() {
		Double lat = currentLat * 1E6;
		Double lng = currentLot * 1E6;

		mapOverlays = mapView.getOverlays();
		mapOverlays.remove(itemizedOverlay);
		if (result != null && result.size() > 0) {
			searchedList = new ArrayList<SearchItem>();
			itemizedOverlay = new ResultPointItemizedOverlay(this
					.getResources().getDrawable(R.drawable.marker),
					bottomDetailViewLayer,searchedList);

			for (JSONObject curObj : result) {
				try {
					SearchItem curItem = new SearchItem();
					curItem.setAddress(curObj.getString("addressLines")
							.replaceAll("\",\"", " ").replaceAll("\"", ""));
					if (curObj.getJSONArray("phoneNumbers").length() > 0) {
						JSONObject phoneObj = curObj.getJSONArray(
								"phoneNumbers").getJSONObject(0);
						curItem.setPhonenumber(phoneObj.getString("number"));
					}
					curItem.setTitle(curObj.getString("title").replaceAll(
							"<b>", "").replaceAll("</b>", ""));
					curItem.setLatitude(Double.parseDouble(curObj
							.getString("lat")));
					curItem.setLongitude(Double.parseDouble(curObj
							.getString("lng")));
					float[] distanceResults = new float[3];
					Location.distanceBetween(currentLat, currentLot, Double
							.parseDouble(curObj.getString("lat")), Double
							.parseDouble(curObj.getString("lng")),
							distanceResults);
					curItem.setDistance(distanceResults[0]);

					searchedList.add(curItem);

					GeoPoint p = new GeoPoint(
							(int) (curItem.getLatitude() * 1E6), (int) (curItem
									.getLongitude() * 1E6));

					OverlayItem overlayitem = new OverlayItem(p, curItem
							.getTitle(), "");

					itemizedOverlay.addOverlay(overlayitem);

				} catch (JSONException e) {
					Log.v("changdoc", "JSON PARSER ERROR");
				}
			}
			mapOverlays.add(itemizedOverlay);
			itemizedOverlay.saveCurrentItem();
			
			mapView.invalidate();
		}

		progressDialog.dismiss();

		GetRandomItemJob getRandomJob = new GetRandomItemJob();

		getRandomJob.execute(searchedList);
	}

	protected void setLocation(Location location, boolean isCurrentLocation) {
		
		Double lat = currentLat * 1E6;
		Double lng = currentLot * 1E6;
		
		mapView.getController().animateTo(new GeoPoint(currentLat.intValue(), currentLot.intValue()) );
		
		

		List<Overlay> mapOverlays = mapView.getOverlays();
		
		Overlay tempCenterOverlay = null;
		
		for(Overlay curOverlay : mapOverlays){
			if(curOverlay instanceof CenterPointOverlay){
				tempCenterOverlay = curOverlay;
				break;
			}
		}
		if(tempCenterOverlay!=null)mapOverlays.remove(tempCenterOverlay);
		
		if(!isCurrentLocation)mapOverlays.clear();
		
		CenterPointOverlay centerOverlay = new CenterPointOverlay(location);
		
		mapOverlays.add(0, centerOverlay);

		mapView.invalidate();

		mapView.getController().animateTo(
				new GeoPoint(lat.intValue(), lng.intValue()));
		
		if(!isCurrentLocation)doBackgroundGetList();
		
		if(onLocationUpdate!=null)
			locationManager.removeUpdates(onLocationUpdate);
	}

	protected boolean isRouteDisplayed() {
		return false;
	}

	protected void setLocationListener() {
		onLocationUpdate = new DisplayLocationListener();
		
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				0, 0, onLocationUpdate);
		Location getLocation = locationManager
				.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		
		if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){  
			AlertDialog.Builder builder = new AlertDialog.Builder(this);  
			builder.setMessage(this.getResources().getString(R.string.gps_off_warning))  
			     .setCancelable(false)  
			     .setPositiveButton(this.getResources().getString(R.string.gps_on),  
			          new DialogInterface.OnClickListener(){  
			          public void onClick(DialogInterface dialog, int id){  
			        	  Intent gpsOptionsIntent = new Intent(  
			                      android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);  
			              startActivity(gpsOptionsIntent);  
			          }  
			     });  
			     builder.setNegativeButton(this.getResources().getString(R.string.cancel),  
			          new DialogInterface.OnClickListener(){  
			          public void onClick(DialogInterface dialog, int id){  
			               dialog.cancel();  
			          }  
			     });  
			AlertDialog alert = builder.create();  
			alert.show();  
		} 
		
		if (getLocation != null) {
			currentLat = getLocation.getLatitude();
			currentLot = getLocation.getLongitude();
			currentLocation = getLocation;
			
		}else{
			Toast.makeText(EatMapActivity.this, this.getResources().getString(R.string.cannot_get_current_location_another),
					Toast.LENGTH_SHORT).show();
			
		}
		
		setLocation(currentLocation,true);

		// locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
		// 1000L, 1, onLocationUpdate);
	}

	protected void doBackgroundGetList() {
		GetListNearByJob getList = new GetListNearByJob();

		getList.execute(getIntent().getExtras().getString("currentCategory"));
		
		firstFlag++;
	}

	@Override
	protected void onResume() {
		super.onResume();
		//currentLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		//setLocationListener();
		/*
		if (currentLocation != null && firstFlag == 0) {
			currentLat = currentLocation.getLatitude();
			currentLot = currentLocation.getLongitude();

			doBackgroundGetList();			
		}
		*/
	}

	@Override
	protected void onPause() {
		super.onPause();
		if(onLocationUpdate!=null)
		locationManager.removeUpdates(onLocationUpdate);
	}

	private class DisplayLocationListener implements LocationListener {

		public void onLocationChanged(Location location) {
			currentLat = location.getLatitude();
			currentLot = location.getLongitude();
			currentLocation = location;

			//setLocation(location);
		}

		public void onProviderDisabled(String provider) {
		}

		public void onProviderEnabled(String provider) {
		}

		public void onStatusChanged(String provider, int status, Bundle extras) {
		}

	}

	private class GetListNearByJob extends
			AsyncTask<String, Integer, ArrayList<JSONObject>> {

		@Override
		protected void onPreExecute() {
			if (currentLat == null || currentLot == null) {
				Toast.makeText(EatMapActivity.this, getApplicationContext().getResources().getString(R.string.cannot_get_current_location),
						Toast.LENGTH_SHORT).show();
				cancel(true);
			} else {
				super.onPreExecute();
				progressDialog = ProgressDialog.show(mapView.getContext(), "",
						"Loading Please wait.. ", true);
			}
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			super.onProgressUpdate(values);
			progressDialog.setMessage("Loading Please wait..\n" + values[0]
					+ "% Completed");
		}

		@Override
		protected void onPostExecute(ArrayList<JSONObject> result) {
			super.onPostExecute(result);
			EatMapActivity.this.result = result;
			progressDialog.setMessage("Displaying Please wait.. ");
			setItemsToMapView();
			// setLocation(currentLocation);
		}

		@Override
		protected ArrayList<JSONObject> doInBackground(String... params) {
			ArrayList<JSONObject> resultList = new ArrayList<JSONObject>();

			String currentAddr = "";

			try {
				List<Address> addresses = geocoder.getFromLocation(currentLat,
						currentLot, 1);
				if (addresses.size() > 0) {
					Address curAddr = addresses.get(0);
					for (int i = 0; i < curAddr.getMaxAddressLineIndex(); i++) {
						currentAddr += curAddr.getAddressLine(i);
					}
				}
			} catch (IOException e1) {
				if (currentLat == null || currentLot == null) {
					Toast.makeText(EatMapActivity.this,
							"Cannot get data from Google Server.", Toast.LENGTH_SHORT)
							.show();
					cancel(true);
				}
			}

			for (String cur : params) {
				String result = new HttpHelper()
						.getResultFromUrl(EatVars.GOOGLE_SEARCH_URL
								+ "?key=ABQIAAAA-yWKzmcGLSLqaJLu60uLFxSWpXNALdVZzRWSotTP-dQtXB8boxRTAbIKBXN1No181QtqVQwx-dKD9g&v=1.0&rsz=large"
								+ "&sll=" + currentLat + "," + currentLot
								+ "&q=" + cur + " loc:" + currentAddr);

				JSONArray jsonArray = null;

				try {
					JSONObject jsonObj = new JSONObject(result);
					if (jsonObj != null
							&& jsonObj.getJSONObject("responseData") != null
							&& jsonObj.getJSONObject("responseData")
									.getJSONArray("results") != null
							&& jsonObj.getJSONObject("responseData")
									.getJSONArray("results").length() > 0) {
						jsonArray = jsonObj.getJSONObject("responseData")
								.getJSONArray("results");
					}
				} catch (JSONException e) {

				}
				if (jsonArray != null) {
					int numberOfParams = jsonArray.length();

					if (jsonArray != null && jsonArray.length() > 0) {
						for (int i = 0; i < jsonArray.length(); i++) {
							try {
								resultList.add(jsonArray.getJSONObject(i));
								publishProgress((int) (((i + 1) / (float) numberOfParams) * 100));

							} catch (JSONException e) {
								e.printStackTrace();
							}
						}
					}
				}

			}

			return resultList;
		}

	}

	public void onClick(View v) {
		if (v.equals(getListButton)) {
			doBackgroundGetList();
		} else if(v.equals(getCurrentLocationButton)){
			setLocationListener();
		}
	}

	private class HttpHelper {

		public String getResultFromUrl(String currentUrl) {
			String url = currentUrl;
			String result = "";
			Log.v("changdoc", "RUnning..Thread" + url.length() + "/" + url);
			try {
				URI uri = new URI("http", url, null);
				HttpGet get = new HttpGet(uri);

				HttpParams hp = new BasicHttpParams();
				HttpConnectionParams.setConnectionTimeout(hp, 5000);

				HttpClient client = new DefaultHttpClient(hp);

				HttpResponse response = client.execute(get);

				if (response != null) {

					HttpEntity entity = response.getEntity();
					result = convertStreamToString(entity.getContent());
				} else {
					return "";
				}

				Log.v("changdoc", "RESULT:" + result);
			} catch (Exception e) {
				result = "error";
			} finally {

			}
			return result;

		}

		private String convertStreamToString(InputStream is) {
			BufferedReader reader = new BufferedReader(
					new InputStreamReader(is), 8 * 1024);
			StringBuilder sb = new StringBuilder();

			String line = null;
			try {
				while ((line = reader.readLine()) != null) {
					sb.append(line + "\n");
				}
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			return sb.toString();
		}

	}

	/*
	 * Random generator Using Async
	 */

	private class GetRandomItemJob extends
			AsyncTask<ArrayList<SearchItem>, String, SearchItem> {

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			progressDialog = ProgressDialog.show(mapView.getContext(), "",
					getApplicationContext().getResources().getString(R.string.choosing_somewhere), true);
		}

		@Override
		protected void onProgressUpdate(String... values) {
			super.onProgressUpdate(values);
			progressDialog.setMessage(getApplicationContext().getResources().getString(R.string.choosing_somewhere)+" \n" + values[0]);
		}

		@Override
		protected void onPostExecute(SearchItem result) {
			super.onPostExecute(result);
			progressDialog.dismiss();
			
			currentSearchItem = result;
			if(currentSearchItem!=null)
				setRandSucces();
			else
				Toast.makeText(EatMapActivity.this,
						"Cannot get data from Google Server.", Toast.LENGTH_SHORT)
						.show();
		}

		@Override
		protected SearchItem doInBackground(ArrayList<SearchItem>... params) {
			SearchItem resultItem = null;
			if (searchedList!=null && searchedList.size() > 0) {
				int startTiming = 1100;
				int choiceIndex = 0;
				int spinCount = 20;
				while (startTiming > 0 && spinCount > 0) {
					try {
						Thread.sleep(startTiming);
						choiceIndex = (int) (Math.random() * searchedList
								.size());
						publishProgress(searchedList.get(choiceIndex)
								.getTitle());
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					if (startTiming - (110 + choiceIndex) > 0)
						startTiming -= (110 + choiceIndex);

					if (startTiming < 110)
						spinCount--;
				}

				resultItem = searchedList.get(choiceIndex);

			}

			return resultItem;
		}

	}

	public void setSearchedItem(final SearchItem cur) {
		TextView title = (TextView) bottomDetailViewLayer
				.findViewById(R.id.title);
		Button phone = (Button) bottomDetailViewLayer.findViewById(R.id.phone);
		TextView distance = (TextView) bottomDetailViewLayer
				.findViewById(R.id.distance);

		title.setText(cur.getTitle());
		if(cur.getDistance()>1)
			distance.setText((int)cur.getDistance() + "m");
		else
			distance.setText("near");
		phone.setText(cur.getPhonenumber());

		phone.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				startActivity(new Intent(Intent.ACTION_CALL, Uri.parse("tel:"
						+ cur.getPhonenumber())));
			}
		});

		bottomDetailViewLayer.setVisibility(RelativeLayout.VISIBLE);

		Button button = (Button) bottomDetailViewLayer
				.findViewById(R.id.bottomMapViewLayoutCloseButton);
		button.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				bottomDetailViewLayer.setVisibility(RelativeLayout.GONE);
			}
		});

		final Button saveButton = (Button) bottomDetailViewLayer
				.findViewById(R.id.bottomMapViewLayoutSaveButton);
		saveButton.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				if(saveCurrentItem()){
					saveButton.setVisibility(Button.GONE);
				}
			}
		});
	}

	public void setRandSucces() {
		
		Toast toast = Toast.makeText(EatMapActivity.this, currentSearchItem.getTitle() +" "+ this.getResources().getString(R.string.selected),
				Toast.LENGTH_LONG);
		toast.setGravity(Gravity.CENTER,0,0);
		toast.show();
		
		Double lat = currentSearchItem.getLatitude() * 1E6;
		Double lng = currentSearchItem.getLongitude() * 1E6;

		mapView.getController().animateTo(
				new GeoPoint(lat.intValue(), lng.intValue()));
		mapView.getController().setZoom(mapView.getMaxZoomLevel());

		setSearchedItem(currentSearchItem);

		GeoPoint p = new GeoPoint(
				(int) (currentSearchItem.getLatitude() * 1E6),
				(int) (currentSearchItem.getLongitude() * 1E6));

		OverlayItem overlayitem = new OverlayItem(p, currentSearchItem
				.getTitle(), "");

		mapView.getOverlays().remove(choicedItemizedOverlay);

		choicedItemizedOverlay = new ChoicedItemizedOverlay(this.getResources()
				.getDrawable(R.drawable.markerchoiced));

		choicedItemizedOverlay.addOverlay(overlayitem);

		mapView.getOverlays().add(choicedItemizedOverlay);

	}

	public boolean saveCurrentItem() {
		try {
			EatDBHelper dbhelper = new EatDBHelper(this);
			SQLiteDatabase sdb = dbhelper.getWritableDatabase();

			ContentValues values = new ContentValues();
			values.put(EatDB.HISTORY_LAT, currentSearchItem.getLatitude());
			values.put(EatDB.HISTORY_LOT, currentSearchItem.getLongitude());
			values.put(EatDB.HISTORY_PHONE, currentSearchItem.getPhonenumber());
			values.put(EatDB.HISTORY_TITLE, currentSearchItem.getTitle());
			values.put(EatDB.HISTORY_REGDATE_LONG, System.currentTimeMillis());

			sdb.insert(EatDB.TABLE_HISTORY, null, values);
			sdb.close();

			Toast.makeText(this, currentSearchItem.getTitle()+this.getResources().getString(R.string.saved), Toast.LENGTH_SHORT).show();
		} catch (Exception e) {
			return false;
		}
		return true;
	}
}
